﻿using System.Collections.Generic;
using System.Diagnostics.Contracts;
using System.Text;

namespace System
{
	internal static class UriExtensions
	{
		private const string nocacheQueryParameter = "nocache";

		public static IEnumerable<Uri> EnsureNoCache(this IEnumerable<Uri> uris)
		{
			Contract.Requires(uris != null);
			Contract.Ensures(Contract.Result<IEnumerable<Uri>>() != null);

			foreach (var uri in uris)
			{
				yield return uri == null ? null : uri.EnsureNoCache();
			}
		}

		public static Uri EnsureNoCache(this Uri uri)
		{
			Contract.Requires(uri != null);
			Contract.Ensures(Contract.Result<Uri>() != null);

			string nocacheValue = nocacheQueryParameter + '=' + Environment.TickCount;

			var builder = new UriBuilder(uri);

			var query = new StringBuilder(builder.Query);

			builder.Query = null;

			if (query.Length > 1)
			{
				// Remove the leading question mark (?)
				query.Remove(0, 1);

				bool updatedNoCache = false;
				int index = 0;

				foreach (var pair in query.ToString().Split('&'))
				{
					Contract.Assume(pair != null);

					var items = pair.Split('=');

					if (items.Length == 2 && string.Equals(items[0], nocacheQueryParameter, StringComparison.Ordinal))
					{
						Contract.Assume(index + pair.Length <= query.Length);

						query.Remove(index, pair.Length);
						query.Insert(index, nocacheValue);

						updatedNoCache = true;
						break;
					}

					index += pair.Length + 1;
				}

				if (!updatedNoCache)
				{
					query.Append('&').Append(nocacheValue);
				}

				builder.Query = query.ToString();
			}
			else
			{
				builder.Query = nocacheValue;
			}

			return builder.Uri;
		}
	}
}